package com.nullpointer.xchatfinal.fragment;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.nullpointer.xchatfinal.MainActivity;
import com.nullpointer.xchatfinal.R;
import com.nullpointer.xchatfinal.adapter.HistoryMessageAdapter;
import com.nullpointer.xchatfinal.database.MessagesDataManager;
import com.nullpointer.xchatfinal.fragment.ChooseFriendDialogFragment.OnChooseFriendDialogFragment;
import com.nullpointer.xchatfinal.fragment.CreatePrivateGroupDialogFragment.OnCreatePrivateGroupDialogFragment;
import com.nullpointer.xchatfinal.object.ChatType;
import com.nullpointer.xchatfinal.object.GroupChat;
import com.nullpointer.xchatfinal.object.GroupMessageContent;
import com.nullpointer.xchatfinal.object.HistoryMessage;
import com.nullpointer.xchatfinal.object.MessageContent;
import com.nullpointer.xchatfinal.object.OnJoinRoomListener;
import com.nullpointer.xchatfinal.object.PrivateMessageContent;
import com.nullpointer.xchatfinal.object.SelectFriend;
import com.nullpointer.xchatfinal.object.TargetChat;
import com.nullpointer.xchatfinal.object.User;
import com.nullpointer.xchatfinal.object.MessageContent.MsgType;
import com.nullpointer.xchatfinal.service.ChatService;
import com.nullpointer.xchatfinal.utils.Common;
import com.nullpointer.xchatfinal.utils.DataManager;
import com.nullpointer.xchatfinal.utils.Error;
import com.nullpointer.xchatfinal.utils.InfoText;
import com.nullpointer.xchatfinal.utils.KiraGameLog;
import com.nullpointer.xchatfinal.utils.Error.ErrorCode;
import com.quickblox.chat.model.QBDialog;
import com.quickblox.core.QBEntityCallbackImpl;
import com.quickblox.core.request.QBRequestGetBuilder;
import com.quickblox.customobjects.QBCustomObjects;
import com.quickblox.customobjects.model.QBCustomObject;

public class MessageFragment extends Fragment {

	private ListView lvMessages;
	private LinearLayout llUpdate;
	private TextView tvUpdateTitle;
	private TextView tvUpdateContent;
	private LinearLayout llFeedback;
	private List<HistoryMessage> data = new ArrayList<HistoryMessage>();
	private HistoryMessageAdapter adapter;
	private boolean isCreatingGroupChat = false;

	public static MessageFragment newInstance() {
		MessageFragment f = new MessageFragment();
		return f;
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View view = inflater.inflate(R.layout.fragment_message, container,
				false);
		findViewIds(view);
		init();
		setEvent();
		return view;
	}

	private void init() {
		adapter = new HistoryMessageAdapter(getActivity(), data);
		lvMessages.setAdapter(adapter);
		loadMessageFromDatabase();
		checkUpdate();
	}

	private void checkUpdate() {
		QBRequestGetBuilder requestBuilder = new QBRequestGetBuilder();
		requestBuilder.setPagesLimit(1);

		QBCustomObjects.getObjects(Common.UpdateObject.UPDATE_CLASS,
				requestBuilder,
				new QBEntityCallbackImpl<ArrayList<QBCustomObject>>() {

					@Override
					public void onSuccess(
							ArrayList<QBCustomObject> customObjects,
							Bundle params) {
						KiraGameLog.d(">>> custom objects: " + customObjects);
						if (customObjects.size() > 0) {
							try {
								QBCustomObject object = customObjects.get(0);
								int versionCode = Integer.parseInt(object
										.getFields()
										.get(Common.UpdateObject.VERSION_CODE)
										.toString());
								String versionName = object.getFields()
										.get(Common.UpdateObject.VERSION_NAME)
										.toString();
								String newFeature = object.getFields()
										.get(Common.UpdateObject.NEW_FEATURE)
										.toString();
								PackageInfo pInfo;

								pInfo = getActivity().getPackageManager()
										.getPackageInfo(
												getActivity().getPackageName(),
												0);
								int currentVersion = pInfo.versionCode;
								if (currentVersion < versionCode) {
									llUpdate.setVisibility(View.VISIBLE);
									llFeedback.setVisibility(View.GONE);
									tvUpdateTitle.setText("Update new version");
									tvUpdateContent.setText("version "
											+ versionName
											+ " is available. Please update!");
								}
							} catch (Exception e) {
								e.printStackTrace();
							}

						}

					}

					@Override
					public void onError(List<String> errors) {
						KiraGameLog.d("check update error " + errors);
					}
				});

	}

	public void refreshData() {
		loadMessageFromDatabase();
	}

	private void setEvent() {
		lvMessages.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				HistoryMessage historyMessage = (HistoryMessage) parent
						.getAdapter().getItem(position);
				if (historyMessage.getChatType() == ChatType.CHAT_PRIVATE) {
					TargetChat targetChat = new TargetChat(historyMessage);
					((MainActivity) getActivity()).showChat(targetChat);
				} else {
					isCreatingGroupChat = false;
					ChatService.getInstance()
							.joinroom(
									historyMessage.getDetailedMessage()
											.getTargetID(),
									historyMessage.getDetailedMessage()
											.getTargetName(), joinRoomListener);
				}
			}
		});

		lvMessages.setOnItemLongClickListener(new OnItemLongClickListener() {

			@Override
			public boolean onItemLongClick(AdapterView<?> parent, View view,
					int position, long id) {
				HistoryMessage historyMessage = (HistoryMessage) parent
						.getAdapter().getItem(position);
				showMenu(historyMessage.getDetailedMessage().getTargetID());
				return true;
			}
		});

		llUpdate.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				showStore();
			}
		});

		llFeedback.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				showFeedbackDialog();
			}
		});
	}

	protected void showFeedbackDialog() {
		try {
			final FeedbackDialogFragment dialog = new FeedbackDialogFragment();
			FragmentTransaction transaction = getActivity()
					.getSupportFragmentManager().beginTransaction();
			transaction.add(dialog, "FeedbackDialogFragment");
			transaction.commitAllowingStateLoss();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void showStore() {
		final String packageName = getActivity().getApplicationContext()
				.getPackageName();
		if (packageName == null)
			return;
		Intent t = new Intent(Intent.ACTION_VIEW);
		t.setData(Uri.parse("market://details?id=" + packageName));
		getActivity().startActivity(t);
	}

	protected void showMenu(final String fromID) {
		AlertDialog.Builder aBuilder = new AlertDialog.Builder(getActivity());
		aBuilder.setItems(new String[] { "Delete message" },
				new Dialog.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						switch (which) {
						case 0:
							MessagesDataManager.getInstance(getActivity())
									.deleteMessageAndHistoryByTargetID(fromID);
							refreshData();
							refreshMessageNum();
							break;
						default:
							break;
						}
					}
				});

		AlertDialog alertDialog = aBuilder.create();
		alertDialog.setCanceledOnTouchOutside(true);
		alertDialog.show();
	}

	protected void refreshMessageNum() {
		try {
			((MainActivity) getActivity()).refreshMessageNum();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void findViewIds(View view) {
		lvMessages = (ListView) view.findViewById(R.id.lv_messages);
		llUpdate = (LinearLayout) view.findViewById(R.id.ll_update);
		tvUpdateTitle = (TextView) view.findViewById(R.id.tv_update_title);
		tvUpdateContent = (TextView) view.findViewById(R.id.tv_update_content);
		llFeedback = (LinearLayout) view.findViewById(R.id.ll_feedback);
	}

	private void loadMessageFromDatabase() {
		showLoadingAnimation();
		data.clear();
		data.addAll(MessagesDataManager.getInstance(getActivity())
				.getAllHistoryMessages(0, 100));
		adapter.notifyDataSetChanged();
		// updateNewMessagesNum();
		hideLoadingAnimation();
	}

	OnJoinRoomListener joinRoomListener = new OnJoinRoomListener() {

		@Override
		public void onPreJoinRoom() {
			KiraGameLog.d("onPreJoinRoom");
			try {
				((Activity) getActivity()).runOnUiThread(new Runnable() {
					@Override
					public void run() {
						showOnPreJoinRoomNotice();
					}
				});
			} catch (Exception e) {
				e.printStackTrace();
			}

		}

		@Override
		public void onJoinRoomSuccessed(final String roomJID,
				final String groupName) {
			KiraGameLog.d("onJoinRoomSuccessed");
			try {
				((Activity) getActivity()).runOnUiThread(new Runnable() {
					@Override
					public void run() {
						doOnJoinRoomSuccessed(roomJID, groupName);
					}
				});
			} catch (Exception e) {
				e.printStackTrace();
			}

		}

		@Override
		public void onJoinRoomFailed(final ErrorCode errorCode,
				final String roomJID, final String groupName) {
			KiraGameLog.d("onJoinRoomFailed");

			try {
				((Activity) getActivity()).runOnUiThread(new Runnable() {
					@Override
					public void run() {
						showJoinRoomErrorNotice(errorCode, roomJID, groupName);
					}
				});

			} catch (Exception e) {
				e.printStackTrace();
			}

		}
	};

	private void showJoinRoomErrorNotice(ErrorCode errorCode,
			final String roomJID, final String groupName) {
		switch (errorCode) {
		case CONNECT_SERVER_ERROR:
			try {
				((MainActivity) getActivity())
						.showConnectServerError(Error.ErrorInfo[errorCode
								.ordinal()]);
			} catch (Exception e) {
				e.printStackTrace();
			}
			break;

		case JOIN_ROOM_FAIL_NOT_MEMBER:
			try {
				((MainActivity) getActivity()).showNotice(false,
						Error.ErrorInfo[errorCode.ordinal()], "RETRY",
						new OnClickListener() {

							@Override
							public void onClick(View v) {
								ChatService.getInstance().joinroom(roomJID,
										groupName, joinRoomListener);
							}
						});
			} catch (Exception e) {
				e.printStackTrace();
			}
			break;

		case JOIN_ROOM_FAIL:
			try {
				((MainActivity) getActivity()).showNotice(false,
						Error.ErrorInfo[errorCode.ordinal()], "RETRY",
						new OnClickListener() {

							@Override
							public void onClick(View v) {
								ChatService.getInstance().joinroom(roomJID,
										groupName, joinRoomListener);
							}
						});
			} catch (Exception e) {
				e.printStackTrace();
			}
			break;

		default:
			break;
		}

	}

	protected void doOnJoinRoomSuccessed(final String roomJID,
			final String groupName) {
		showGroupChat(roomJID, groupName);
		if (isCreatingGroupChat) {
			sendCreateNewGroupMessageToGroup(roomJID, groupName);
			isCreatingGroupChat = false;
		}
	}

	protected void showGroupChat(String roomJID, String groupName) {
		try {
			TargetChat targetChat = new TargetChat(ChatType.CHAT_GROUP,
					roomJID, groupName);
			((MainActivity) getActivity()).showChat(targetChat);
			((MainActivity) getActivity()).hideNotice();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	protected void showPrivateChat(String userID, String userName) {
		try {
			TargetChat targetChat = new TargetChat(ChatType.CHAT_PRIVATE,
					userID, userName);
			((MainActivity) getActivity()).showChat(targetChat);
			((MainActivity) getActivity()).hideNotice();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void showOnPreJoinRoomNotice() {
		try {
			((MainActivity) getActivity()).showNotice(true,
					InfoText.JOINING_GROUP, null, null);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void createNewChat() {
		try {
			final ChooseFriendDialogFragment dialog = ChooseFriendDialogFragment
					.newInstance(null, null);
			dialog.setOnChooseFriendDialogFragment(new OnChooseFriendDialogFragment() {

				@Override
				public void onChooseFriend(final List<SelectFriend> users) {
					if (users.size() == 0) {
						return;
					}
					KiraGameLog.d("list choose friend " + users);
					if (users.size() == 1) {
						SelectFriend user = users.get(0);
						showPrivateChat(user.getUserID(), user.getUserName());
					} else {
						try {
							final CreatePrivateGroupDialogFragment dialog = CreatePrivateGroupDialogFragment
									.newInstance(users);

							dialog.setOnCreatePrivateGroupDialogFragment(new OnCreatePrivateGroupDialogFragment() {

								@Override
								public void onCreated(QBDialog qbDialog) {
									isCreatingGroupChat = true;
									joinChat(qbDialog);
									notifyMemberJoinGroup(qbDialog,
											qbDialog.getOccupants());
								}
							});
							FragmentTransaction transaction = getActivity()
									.getSupportFragmentManager()
									.beginTransaction();
							transaction
									.add(dialog, "CreateGroupDialogFragment");
							transaction.commitAllowingStateLoss();
						} catch (Exception e) {
							e.printStackTrace();
						}
					}

				}

				@Override
				public void onCancel() {

				}
			});
			FragmentTransaction transaction = getActivity()
					.getSupportFragmentManager().beginTransaction();
			transaction.add(dialog, "ChooseFriendDialogFragment");
			transaction.commitAllowingStateLoss();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	protected void sendCreateNewGroupMessageToGroup(final String roomJID,
			final String groupName) {
		User currentUser = DataManager.getInstance(getActivity())
				.getCurrentUser();
		String currentUserName = currentUser.getName();
		MessageContent msg = new MessageContent(currentUser.getUserID());
		msg.setName(currentUserName);
		String content = currentUserName + " create this group";
		msg.setContent(content);
		msg.setAvatarID(currentUser.getUserInfo().getAvatarID());
		msg.setMsgType(MsgType.UPDATE_GROUP_INFO);

		GroupMessageContent groupMessageContent = new GroupMessageContent();
		groupMessageContent.setMessageContent(msg);
		groupMessageContent.setFromGroupJID(roomJID);
		groupMessageContent.setFromGroupName(groupName);
		ChatService.getInstance().sendMessageChatGroup(groupMessageContent,
				null);
	}

	protected void notifyMemberJoinGroup(QBDialog qbDialog,
			ArrayList<Integer> occupants) {
		GroupChat groupChat = new GroupChat();
		groupChat.setName(qbDialog.getName());
		groupChat.setGroupJID(qbDialog.getRoomJid());
		for (Integer userID : occupants) {
			PrivateMessageContent privateMessageContent = new PrivateMessageContent(
					getActivity(), groupChat.toJson(), MsgType.ADD_GROUP,
					Integer.toString(userID));
			ChatService.getInstance().sendMessagePrivate(privateMessageContent,
					null);

		}
	}

	protected void joinChat(QBDialog qbDialog) {
		ChatService.getInstance().joinroom(qbDialog.getRoomJid(),
				qbDialog.getName(), joinRoomListener);
	}

	public void showLoadingAnimation() {
		try {
			((MainActivity) getActivity()).startRefeshAnimation();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void hideLoadingAnimation() {
		try {
			((MainActivity) getActivity()).stopRefeshAnimation();
			((MainActivity) getActivity()).hideInfo();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
